from backtrader import Strategy
from utils.logger import Loggers

class BaseStrategy(Strategy):
    """
    需继承并实现以下方法:
    - init_indicators: 初始化技术指标
    - generate_signal: 生成交易信号
    """
    def __init__(self):
        self.logger = Loggers('交割单')
        
        self.logger.info('==================策略开始==================')
        self.logger.info(f'初始本金: {self.broker.getvalue()}')

        # 记录数据
        self.equity_curve = []  # 资金曲线
        self.trades = []  # 交易记录
        self.last_trade_size = 0  # 用于记录上一次交易的开仓规模
        self.highest_price = 0 #历史最高
        self.lowest_price = 0 # 历史最低


    # 记录资金曲线
    def logEquity(self):
        # 自动记录资金曲线
        self.equity_curve.append({
            "date":self.data.datetime.datetime(),
            "value":self.broker.getvalue(),
            "close":self.data.close[0],
            "open":self.data.open[0],
        })
    
    
    def next(self):
        self.logEquity()

    # 交易通知 当完成交易后 会发起该通知
    def notify_trade(self, trade):
        if not trade.isclosed:
            return
        # 计算本次交易的盈亏比率
        if trade.price != 0 :
            pnl_ratio = (trade.pnl / (trade.price * abs(self.last_trade_size))) * 100
        else:
            pnl_ratio = 0
        
        # 获取当前剩余本金
        current_cash = self.broker.getvalue()
        # 计算仓位总盈亏
        oldcurrent_cash = current_cash + trade.pnl
        pnl_ratio2 = trade.pnlcomm / oldcurrent_cash *100
        self.log(f'交易盈亏, 毛利: {trade.pnl:.2f}, 净利: {trade.pnlcomm:.2f}  剩余本金: {current_cash:.2f} 盈亏: {pnl_ratio:.2f}% 账户盈亏: {pnl_ratio2:.2f}%')

    # 自动记录订单交割单
    def notify_order(self, order):
        if order.status in [order.Submitted, order.Accepted]:
            # 订单已提交/接受, 无需记录
            return
        dt =  self.datas[0].datetime.datetime(0)

        # 检查订单是否已完成
        if order.status in [order.Completed]:
            if order.isbuy():
                if self.position.size == 0:
                    self.log(f'平空, 价格: {order.executed.price:.6f}, 数量: {order.executed.size:.5f},价值: {(order.executed.price * order.executed.size):.2f}')
                    self.highest_price = 0 # 清除记录
                    self.lowest_price = 0 # 清除记录
                else:
                    self.log(f'开多, 价格: {order.executed.price:.6f}, 数量: {order.executed.size:.5f}, 佣金: {order.executed.comm:.2f},价值: {(order.executed.price * order.executed.size):.2f}')
                    self.last_trade_size = order.executed.size  # 记录开仓规模
                    self.highest_price = order.executed.price # 记录
                    self.lowest_price = order.executed.price # 记录
                    
            elif order.issell():
                if self.position.size == 0:
                    self.log(f'平多, 价格: {order.executed.price:.6f}, 数量: {order.executed.size:.5f},价值: {(order.executed.price * order.executed.size):.2f}')
                    self.highest_price = 0 # 清除记录
                    self.lowest_price = 0 # 清除记录
                else:
                    self.log(f'开空, 价格: {order.executed.price:.6f}, 数量: {order.executed.size:.5f}, 佣金: {order.executed.comm:.2f},价值: {(order.executed.price * order.executed.size):.2f}')
                    self.last_trade_size = order.executed.size  # 记录开仓规模
                    self.highest_price = order.executed.price # 记录
                    self.lowest_price = order.executed.price # 记录

            self.bar_executed = len(self)

        elif order.status in [order.Canceled, order.Margin, order.Rejected]:
            statusText = {order.Canceled:'订单取消',order.Margin:'保证金不足',order.Rejected:'拒绝'}
            self.log(f'开仓失败{order}, err: {statusText[order.status]},atr{self.atr[0]}')
                    
    @property
    def entry_price(self):
        """获取当前持仓成本价"""
        return self.position.price if self.position else None
    
    def log(self, txt, dt=None):
        dt = dt or self.datas[0].datetime.datetime(0)
        # print(f'{dt}, {txt}')
        self.logger.info(f'{dt}, {txt}')